package com.xjscrm.console.chat.dispatch.match.impl;

import cn.hutool.core.util.RandomUtil;
import com.xjscrm.console.chat.cache.CacheHolder;
import com.xjscrm.console.chat.dispatch.match.AllocateRule;
import com.xjscrm.console.dto.chat.setting.ChatAllocateRuleJsonDTO;
import com.xjscrm.console.service.customer.chat.ChatTalkSessionStaffRelService;
import com.xjscrm.console.service.customer.merchat.MerchatChildDeviceRelationService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author mingyang.chen create in 2024/3/20 10:21
 */
@Component
@Slf4j
public class StaffAllocateRule implements AllocateRule {

    @Autowired
    private CacheHolder cacheHolder;
    @Autowired
    private MerchatChildDeviceRelationService merchatChildDeviceRelationService;
    @Autowired
    private ChatTalkSessionStaffRelService talkSessionStaffRelService;

    public static void main(String[] args) {
        List<Node> nodeSet = new ArrayList<>();
        nodeSet.add(new Node(1, 10));
        nodeSet.add(new Node(2, 10));
        nodeSet.add(new Node(3, 10));

        nodeSet.sort(((o1, o2) -> o2.getLess().compareTo(o1.getLess())));
        System.out.println(nodeSet);
    }

    @Override
    public Long allocateStaffId(Long merId, Long deviceUniqueId, ChatAllocateRuleJsonDTO allocateRule) {

        //
        ChatAllocateRuleJsonDTO.StaffAllocate staff = allocateRule.getStaff();
        Integer mode = staff.getMode();

        //
        List<Long> deviceStaffs = merchatChildDeviceRelationService.listStaffIdsByDeviceUniqueId(merId, deviceUniqueId);
        if (ObjectUtils.isEmpty(deviceStaffs)) {
            return null;
        }
        int onlineLimitCount = 0;

        if (Objects.equals(100, mode)) {
            log.info("员工分配: 进入负载均衡分配模式: {}", deviceUniqueId);
            List<Node> nodes = new ArrayList<>();

            //
            for (Long staffId : deviceStaffs) {
                //
                String staffTag = cacheHolder.getStaffTag(staffId);
                //
                if (StringUtils.isBlank(staffTag)) {
                    log.error("优先分配: 员工未上线, 当前员工不计入分发: {}", staffId);
                    continue;
                }
                //
                Integer tempSessionNowCount = talkSessionStaffRelService.countByStaffId(merId, staffId);
                //
                Integer tempSessionCount = cacheHolder.getStaffSessionCount(merId, staffId);

                if (tempSessionNowCount >= tempSessionCount) {
                    log.error("优先分配: 当前员工分配的会话数已上限: {}", staffId);
                    onlineLimitCount++;
                    continue;
                }
                //
                if (Objects.equals(tempSessionNowCount, 0)) {
                    return staffId;
                }
                Node node = new Node(tempSessionNowCount, tempSessionCount);
                node.setStaffId(staffId);
                nodes.add(node);
            }
            if (ObjectUtils.isEmpty(nodes)) {
                log.error("优先分配: 分配失败->会话数已上限/未上线: {}", deviceUniqueId);
                return onlineLimitCount > 0 ? -100L : -101L;
            }
            nodes.sort(((o1, o2) -> o2.getLess().compareTo(o1.getLess())));
            log.info("优先分配: 当前机器人:[{}], 分配员工结果:[{}]", deviceUniqueId, nodes);
            return nodes.get(0).getStaffId();
        }
        //
        else {
            log.info("员工分配: 进入随机分配模式: {}", deviceUniqueId);
            ArrayList<Long> copy = new ArrayList<>();

            for (Long staffId : deviceStaffs) {
                //
                Integer tempSessionNowCount = talkSessionStaffRelService.countByStaffId(merId, staffId);
                Integer tempSessionCount = cacheHolder.getStaffSessionCount(merId, staffId);

                if (tempSessionNowCount >= tempSessionCount) {
                    log.error("随机分配: 当前员工分配的会话数已上限: {}", staffId);
                    onlineLimitCount++;
                    continue;
                }
                String staffTag = cacheHolder.getStaffTag(staffId);
                if (StringUtils.isBlank(staffTag)) {
                    log.error("随机分配: 员工未上线, 当前员工不计入分发");
                    continue;
                }
                copy.add(staffId);
            }
            if (ObjectUtils.isEmpty(copy)) {
                log.error("随机分配: 分配员工失败: 会话数已上限/未上线: {}", deviceUniqueId);
                return onlineLimitCount > 0 ? -100L : -101L;
            }
            int randomInx = RandomUtil.randomInt(copy.size());
            return copy.get(randomInx);
        }
    }

    @Data
    private static class Node {

        private Long staffId;
        private Integer nowCount;
        private Integer count;

        public Node(Integer nowCount, Integer count) {
            this.nowCount = nowCount;
            this.count = count;
        }

        public Integer getLess() {
            return this.count - this.nowCount;
        }

        @Override
        public String toString() {
            return "Node{" +
                    "staffId=" + staffId +
                    ", nowCount=" + nowCount +
                    ", count=" + count +
                    '}';
        }
    }
}
